﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Aquarinum.WebSocekt.Client;
using Aquarinum.WebSocket.Server.WinService.Utils;
using Newtonsoft.Json;
using Topshelf;

namespace Aquarinum.WebSocket.Server.WinService
{
    public class WebSocketSelfHostService : ServiceControl
    {
        private Process _webserviceprocess;

        public bool Start(HostControl hostControl)
        {
            hostControl.RequestAdditionalTime(TimeSpan.FromSeconds(10));
            InitServer();
            return true;
        }

        public bool Stop(HostControl hostControl)
        {
            _webserviceprocess.Kill();
            _webserviceprocess.Dispose();
            GC.Collect();
            Console.WriteLine("windows服务已停止");
            ShellLogger.GetInstance().Info("windows服务已停止");
            return true;
        }

        /// <summary>
        ///     当服务器失去响应
        /// </summary>
        public void OnServerClose()
        {
            var config=new WebSocketServerConfig();
            bool isRetried = false;
            
            for (int i = 0; i < config.RetryTimes; i++)
            {
                Thread.Sleep(5*1000);
                _webserviceprocess.Kill();
                if (InitServer())
                {
                    isRetried = true;
                    break;
                }

                
            }

            if (!isRetried)
            {
                ShellLogger.GetInstance().Info($"websocket服务已停止，经过{config.RetryTimes}重试，启动失败");
            }

        }

        /// <summary>
        ///     初始化OwinServer
        /// </summary>
        private bool InitServer()
        {
            try
            {
                var config = new WebSocketServerConfig();
                var processStartInfo = new ProcessStartInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                    "WebSocketServer",
                    "Aquarinum.WebSocket.Server.exe"))
                {
                    Arguments = JsonConvert.SerializeObject(config).EncodeBase64(),

                    WorkingDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
                        "WebSocketServer")
                };
                if (config.Environment == "dev")
                {
                    processStartInfo.CreateNoWindow = false;
                    processStartInfo.UseShellExecute = true;
                }
                else
                {
                    processStartInfo.CreateNoWindow = true;
                    processStartInfo.UseShellExecute = false;
                }

                _webserviceprocess = new Process
                {
                    StartInfo = processStartInfo
                };

                _webserviceprocess.Start();

                var websocketClient = WebsocketClientFactory.GetDefaultClient();
                var isConnected = false;
                websocketClient.InitClient("ServerShell", "", config.Host);

                websocketClient.OnClientOpened += (o, args) => { isConnected = true; };

                websocketClient.OnClientClosed += (o, args) => { OnServerClose(); };
                websocketClient.OnClientConnected += (o, args) => { isConnected = true; };

                #region 尝试连接

                Thread.Sleep(5*1000);
                websocketClient.ConnectServer();

                for (var i = 0; i < config.TimeOutSeconds; i++)
                {
                    Thread.Sleep(1000);
                    try
                    {
                        if (isConnected) break;
                    }
                    catch (Exception e)
                    {
                        ShellLogger.GetInstance().Error(e);
                    }
                }

                #endregion

                if (!isConnected)
                {
                    Console.WriteLine($"WebSocket服务:{config.Host}启动失败");
                }
                else
                {
                    Console.WriteLine($"当前挂载host:{config.Host}");
                    return true;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("WebSocket服务启动失败");
                ShellLogger.GetInstance().Error(e);
                Console.WriteLine(e.ToString());
            }

            return false;
        }

        public bool Pause(HostControl hostControl)
        {
            _webserviceprocess.Kill();
            _webserviceprocess.Dispose();
            GC.Collect();
            Console.WriteLine("windows服务已暂停");
            ShellLogger.GetInstance().Info("windows服务已暂停");
            return true;
        }

        public bool Continue(HostControl hostControl)
        {
            hostControl.RequestAdditionalTime(TimeSpan.FromSeconds(10));
            InitServer();
            Console.WriteLine("windows服务已继续");
            ShellLogger.GetInstance().Info("windows服务已继续,但web服务未重新启动");
            return true;
        }
    }
}